package org.swingplus.core.scanner;

import org.swingplus.core.annotation.Style;
import org.swingplus.core.annotation.bean.Bean;
import org.swingplus.core.annotation.bean.ReturnType;
import org.swingplus.core.annotation.layout.Layout;
import org.swingplus.core.annotation.widget.Widget;
import org.swingplus.core.bean.DefinitionMetadata;
import org.swingplus.core.bean.RootBeanDefinition;
import org.swingplus.core.context.ApplicationContext;
import org.swingplus.core.exception.BeanCreateException;
import org.swingplus.core.factory.AbstractAutowireBeanFactory;
import org.swingplus.core.factory.config.BeanDefinition;
import org.swingplus.core.util.AnnoManageUtil;
import org.swingplus.core.utils.ClassFileInfoParse;
import org.swingplus.core.utils.ClassFileInfoParseUtil;
import org.swingplus.core.utils.ObjectConvertUtil;
import org.swingplus.core.utils.StringUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BeanScan {

	private static final Logger logger = LoggerFactory.getLogger(BeanScan.class);

	public static void scan() {
		doScan();
	}

	/**
	 * 方法上声明用@Bean
	 *
	 * @param clazz
	 */
	public static void doScan() {
		Set<BeanDefinition> beanDefinitions=new LinkedHashSet<>(0);

		Map<Class,Class[]> map=new HashMap<>();
//        List<Object> instance=new ArrayList<>();
		@SuppressWarnings("rawtypes")
		Class[] clazzs=new Class[]{Layout.class,Style.class,Widget.class};
		for (Class cls:clazzs){
			Set<Class<?>> classesList = AnnoManageUtil.getTypesAnnotatedWith("",cls);
			for (Class class1 : classesList) {
				if(AnnoManageUtil.existAutowiredConstructors(class1)) {
					//构造注入
					AbstractAutowireBeanFactory.constructorSingletonObjectsClass.add(class1);
				}else {
					//set注入
					AbstractAutowireBeanFactory.fieldsSingletonObjectsClass.add(class1);
				}

				DefinitionMetadata definitionMetadata = ClassFileInfoParseUtil.getDefinitionMetadata(class1);
				RootBeanDefinition rootBeanDefinition = ObjectConvertUtil.definitionMetadataToRootBeanDefinition(definitionMetadata);
				beanDefinitions.add(rootBeanDefinition);

			}

//            List<Object> objs=AnnoManageUtil.createBeanByAnnotationsType(packageName,cls);
			List<Object> objs= null;
//            for (Object obj : objs) {
//            	if(AnnoManageUtil.existAutowiredConstructors(obj.getClass())) {
//            		//构造注入
//            		AbstractAutowireBeanFactory.constructorSingletonObjects.put(obj.getClass().getSimpleName(),obj);
//            	}else {
//            		//set注入
//            		AbstractAutowireBeanFactory.fieldsSingletonObjects.put(obj.getClass().getSimpleName(),obj);
//            	}
//			}
			map.put(cls,clazzs);
		}

//		return null;

	}






	/**
	 * 方法上声明用@Bean
	 * 
	 * @param clazz
	 */
	public static void scan(List<Object> instance) {

//		List<Object> instance = new ArrayList<>();
		for (Object object : instance) {
			scan(object);
		}
		return;

	}
	public static void scan(Object instance) {
		Method[] methods = instance.getClass().getDeclaredMethods();
		for (Method method : methods) {
//    	   Bean bean=method.getAnnotation(Bean.class);
//			method.getAnnotatedExceptionTypes();
			Bean bean = method.getAnnotation(Bean.class);
			if (null == bean) {
				continue;
			}
			String instanceName = "";
			String beanValue = bean.value();
			if (!"".equals(beanValue)) {
				instanceName = beanValue;
			} else {
				instanceName = method.getName();
			}
			// 是否指定了ReturnType注解特定声明的类类型
			ReturnType returnType = method.getAnnotation(ReturnType.class);
			Class cls = null;
			if (null != returnType) {
				cls = returnType.value();
			} else {
				// 如果没有指定的ReturnType注解用方法的返回类型设置bean,
				// TODO 如果是返回类型是接口会有问题
//    	     cls=method.getReturnType();
				cls = method.getReturnType();
			}






			Object obj=null;
			try {
				Class[] parameterTypes = method.getParameterTypes();
                if(parameterTypes==null||parameterTypes.length==0){
					obj = cls.newInstance();
				}else {

					//参数类型数组
					//根据参数类型获取相应的构造函数
					Constructor constructor = null;
					try {
						constructor = cls.getConstructor(parameterTypes);
					} catch (NoSuchMethodException e) {
						e.printStackTrace();
					}

					obj=constructor;
				}
//				//参数数组
//				Object[] parameters={1,1};
//				//根据获取的构造函数和参数，创建实例
//				Object o=constructor.newInstance(parameters);



			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(null==obj) {
				throw new BeanCreateException("");
			}

			// 首字母看是不是小写的
			instanceName = Character.isLowerCase(instanceName.charAt(0)) == true ? instanceName
					: StringUtil.lowerFirst(instanceName); // 大写转小写方法

			// ApplicationConetext.getBean();
			boolean flag = ApplicationContext.isExistsKey(instanceName);
			if (flag) {
				logger.error("{} {} already exists in applicatonContext container", instance.getClass(), instanceName);
				throw new BeanCreateException("");
			}
			ApplicationContext.setBean(instanceName, obj);
		}
		return;

	}
}
